设置dispatch
函数,swoole
底层了内置了5
种dispatch_mode
,如果仍然无法满足需求。可以使用编写C++
函数或PHP
函数,实现dispatch
逻辑。使用方法:
$serv->set(array(
'dispatch_func' => 'my_dispatch_function',
));
- 设置
dispatch_func
后底层会自动忽略dispatch_mode
配置 dispatch_func
对应的函数不存在,底层将抛出致命错误- 如果需要
dispatch
一个超过8K
的包,dispatch_func
只能获取到0-8180
字节的内容
dispatch_func
在1.9.7
或更高版本可用
dispatch_func
在1.9.18
或更高版本可以设置为PHP
函数
dispatch_func
仅在SWOOLE_PROCESS
模式下有效,UDP/TCP/UnixSocket
均有效
由于ZendVM
无法支持多线程环境,即使设置了多个Reactor
线程,同一时间只能执行一个dispatch_func
。因此底层在执行此PHP
函数时会进行加锁操作,可能会存在锁的争抢问题。请勿在dispatch_func
中执行任何阻塞操作,否则会导致Reactor
线程组停止工作。
$serv->set(array(
'dispatch_func' => function ($serv, $fd, $type, $data) {
var_dump($fd, $type, $data);
return intval($data[0]);
},
));
$fd
为客户端连接的唯一标识符,可使用Server::getClientInfo
获取连接信息$type
数据的类型,0
表示来自客户端的数据发送,4
表示客户端连接关闭,5
表示客户端连接建立$data
数据内容,需要注意:如果启用了Http
、EOF
、Length
等协议处理参数后,底层会进行包的拼接。但在dispatch_func
函数中只能传入数据包的前8K
内容,不能得到完整的包内容。- 必须返回一个
[0-serv->worker_num)
的数字,表示数据包投递的目标工作进程ID - 小于
0
或大于等于serv->worker_num
为异常目标ID,dispatch
的数据将会被丢弃
在其他PHP扩展中,使用swoole_add_function
注册长度函数到Swoole
引擎中。
C++函数调用时底层不会加锁,需要调用方自行保证线程安全性
int dispatch_function(swServer *serv, swConnection *conn, swEventData *data);
int dispatch_function(swServer *serv, swConnection *conn, swEventData *data)
{
printf("cpp, type=%d, size=%d\n", data->info.type, data->info.len);
return data->info.len % serv->worker_num;
}
int register_dispatch_function(swModule *module)
{
swoole_add_function("my_dispatch_function", (void *) dispatch_function);
}
dispatch
函数必须返回投递的目标worker进程id- 返回的
worker_id
不得超过serv->worker_num
,否则底层会抛出段错误 - 返回负数(
return -1
)表示丢弃此数据包 data
可以读取到事件的类型和长度conn
是连接的信息,如果是UDP
数据包,conn
为NULL